package com.shfl.servermanage.logic.service.impl;

import com.shfl.servermanage.exception.ApiException;
import com.shfl.servermanage.logic.bean.*;
import com.shfl.servermanage.logic.constants.CommonConstants;
import com.shfl.servermanage.logic.model.request.RefactorRequest;
import com.shfl.servermanage.logic.service.*;
import com.shfl.servermanage.logic.utils.FileUtils;
import com.shfl.servermanage.shell.RemoteConnectUtil;
import com.shfl.servermanage.shell.info.RemoteConnectInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.io.File;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class ReleaseServiceImpl implements ReleaseService {

    @Autowired
    private SysExecutableFileService sysExecutableFileService;

    @Autowired
    private SysServerSiteService sysServerSiteService;

    @Autowired
    private SysServerShellService sysServerShellService;

    @Autowired
    private SysAttachmentService sysAttachmentService;

    @Autowired
    private SysReleaseLogServer sysReleaseLogService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void execute(RefactorRequest releaseExecuteRequest) throws Exception {
        String path = CommonConstants.FILE_ADDRESS;
        SysExecutableFile sysExecutableFile = sysExecutableFileService.selectByPrimaryKey(releaseExecuteRequest.getExecutableFileId());
        Map<String, Object> objectMap = new HashMap<>();
        objectMap.put("deleteFlg", CommonConstants.DeleteFlg.NOT_DELETE.getCode());
        objectMap.put("relationId", sysExecutableFile.getId());
        objectMap.put("attachType", CommonConstants.AttachType.EXECUTABLE_FILES.getValue());
        List<SysAttachment> sysAttachmentList = sysAttachmentService.findByMap(objectMap);
        if (CollectionUtils.isEmpty(sysAttachmentList)) {
            throw new ApiException("没有可执行文件");
        }
        if (sysAttachmentList.size() != 1) {
            throw new ApiException("仅可执行一条可执行文件");
        }
        SysAttachment sysAttachment = sysAttachmentList.get(0);
        SysServerSite sysServerSite = sysServerSiteService.selectByPrimaryKey(releaseExecuteRequest.getSiteId());
        if (sysServerSite == null) {
            throw new ApiException("没有可执行的站点");
        }
        objectMap = new HashMap<>();
        objectMap.put("deleteFlg", CommonConstants.DeleteFlg.NOT_DELETE.getCode());
        objectMap.put("serviceId", sysServerSite.getServiceId());
        List<SysServerShell> sysServerShellList = sysServerShellService.findListByMap(objectMap);
        if (CollectionUtils.isEmpty(sysServerShellList)) {
            throw new ApiException("没有可执行的站点");
        }
        if (sysServerShellList.size() != 1) {
            throw new ApiException("仅可有一条执行站点");
        }
        SysServerShell sysServerShell = sysServerShellList.get(0);

        Long startTime = System.currentTimeMillis();
        RemoteConnectInfo info = new RemoteConnectInfo(sysServerShell.getShellIp(), sysServerShell.getShellPort(), sysServerShell.getShellName(), sysServerShell.getShellPassword());
        // 上传文件
        RemoteConnectUtil.uploadFile(info
                , new File(path + sysAttachment.getAttachUrl())
                , sysAttachment.getFileSize()
                , sysServerSite.getSiteDirectory()
                , null);

        StringBuilder sb = new StringBuilder();
        // 执行shell脚本
        RemoteConnectUtil.sendShell(info, "cd " + sysServerSite.getSiteDirectory() + ";" + releaseExecuteRequest.getSiteShell(), sb);
        // 保存shell脚本执行文件
        String filePath = FileUtils.uploadFile(path, sb);
        Long endTime = System.currentTimeMillis();
        // 记录日志
        SysReleaseLog sysReleaseLog = new SysReleaseLog();
        sysReleaseLog.setServiceId(sysServerSite.getServiceId());
        sysReleaseLog.setSiteShell(releaseExecuteRequest.getSiteShell());
        sysReleaseLog.setSiteId(sysServerSite.getId());
        sysReleaseLog.setReleaseTime(endTime - startTime);
        sysReleaseLog.setCreateDate(new Date());
        sysReleaseLog.setExecutableFileVersion(sysExecutableFile.getExecutableVersion());
        sysReleaseLogService.insertSelective(sysReleaseLog);
        SysAttachment addSysAttachment = new SysAttachment();
        addSysAttachment.setAttachUrl(filePath);
        addSysAttachment.setRelationId(sysReleaseLog.getId());
        addSysAttachment.setAttachType(CommonConstants.AttachType.SHELL_LOG.getValue());
        sysAttachmentService.insertSelective(addSysAttachment);
    }
}
